package com.mingqijia.gassafety.webserver.utils;


import com.alibaba.fastjson.JSONObject;
import com.mingqijia.gassafety.webserver.response.baidu.BaiDuDetailResp;
import com.mingqijia.gassafety.webserver.response.baidu.BaiDuResp;
import feign.template.UriUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

@Slf4j
@Component
public class CoordinatesTransitionUtil {

    /*GCJ-02(火星坐标系，WGS84坐标系加密后的坐标系；Google国内地图、高德、QQ地图 使用) 和 BD-09 （百度坐标）
     *    算法代码如下，其中 bd_encrypt 将 GCJ-02 坐标转换成 BD-09 坐标， bd_decrypt 反之。
     */
    static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;

    static double DIGIT = 1000000.0;

    public static String URL = "https://api.map.baidu.com/geoconv/v2/?";

    //高德转百度
    public static String bdEncrypt(double gg_lon, double gg_lat){
        double x = gg_lon, y = gg_lat;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
        double bd_lon = z * Math.cos(theta) + 0.0065;
        double bd_lat = z * Math.sin(theta) + 0.006;
        log.info("gg_lon:{},gg_lon:{}",bd_lon,bd_lat);
        String coordinates = bd_lon + "," + bd_lat;
        return coordinates;
    }

    //百度转高德
    public static String[] bd_decrypt(double bd_lon, double bd_lat){
        double x = bd_lon - 0.0065, y = bd_lat - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        double gg_lon = z * Math.cos(theta);
        double gg_lat = z * Math.sin(theta);
        log.info("gg_lon:{},gg_lon:{}",gg_lon,gg_lon);
        String[] coordinates = new String[2];
        coordinates[0] = String.valueOf(gg_lon);
        coordinates[1] = String.valueOf(gg_lat);
        return coordinates;
    }

    //高德转百度
    public static double[] bdEncrypts(double gg_lon, double gg_lat){
        double x = gg_lon, y = gg_lat;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
        double bd_lon = z * Math.cos(theta) + 0.0065;
        double bd_lat = z * Math.sin(theta) + 0.006;
        log.info("gg_lon:{},gg_lon:{}",bd_lon,bd_lat);
        double[] coordinates = new double[2];
        coordinates[0] = bd_lon;
        coordinates[1] = bd_lat;
        return coordinates;
    }

    /**
     * 默认ak
     * 选择了ak，使用IP白名单校验：
     * 根据您选择的AK已为您生成调用代码
     * 检测到您当前的ak设置了IP白名单校验
     * 您的IP白名单中的IP非公网IP，请设置为公网IP，否则将请求失败
     * 请在IP地址为xxxxxxx的计算发起请求，否则将请求失败
     *
     * model 为1代表高德转百度
     */
    public static List<BaiDuDetailResp> requestGetAK(String coords, String baiDuMapsKey) {
        List<BaiDuDetailResp> baiDuDetailResps = new ArrayList<>();
        try {
            Map<String, String> param = new LinkedHashMap();
            param.put("coords", coords);
            param.put("model", "1");
            param.put("ak", baiDuMapsKey);

            StringBuffer queryString = new StringBuffer();
            queryString.append(URL);
            for (Map.Entry<?, ?> pair : param.entrySet()) {
                queryString.append(pair.getKey() + "=");
                //    第一种方式使用的 jdk 自带的转码方式  第二种方式使用的 spring 的转码方法 两种均可
                //    queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8").replace("+", "%20") + "&");
                queryString.append(UriUtils.encode((String) pair.getValue(), "UTF-8".isEmpty()) + "&");
            }

            if (queryString.length() > 0) {
                queryString.deleteCharAt(queryString.length() - 1);
            }

            URL url = new URL(queryString.toString());
            log.info(queryString.toString());
            URLConnection httpConnection = (HttpURLConnection) url.openConnection();
            httpConnection.connect();

            InputStreamReader isr = new InputStreamReader(httpConnection.getInputStream());
            BufferedReader reader = new BufferedReader(isr);
            StringBuffer buffer = new StringBuffer();
            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            reader.close();
            isr.close();
            log.info("AK: " + buffer.toString());
            BaiDuResp baiDuResp = JSONObject.parseObject(buffer.toString(), BaiDuResp.class);
            if (baiDuResp != null && baiDuResp.getStatus() == 0) {
                List<BaiDuDetailResp> duRespResult = baiDuResp.getResult();
                for (BaiDuDetailResp baiDuDetailResp : duRespResult) {
                    BaiDuDetailResp detailResp = new BaiDuDetailResp();
                    detailResp.setX(Math.round(baiDuDetailResp.getX() * DIGIT) / DIGIT);
                    detailResp.setY(Math.round(baiDuDetailResp.getY() * DIGIT) / DIGIT);
                    baiDuDetailResps.add(detailResp);
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return baiDuDetailResps;
    }
}
